﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////

// Reviewed

#pragma once
#include "GcmpModelInterface.h"
#include "GcmpApiDeclaration.h"
#include "ModelViewEnums.h"
#include "WeakPtr.h"
#include "IElement.h"
#include "Vector3d.h"
#include "NdbDataSchema.h"
#include "ElementCreationOptions.h"

namespace gcmp
{
    class IDocument;
    class IPlane;
    class IWorkPlane;
    class IGraphicsPlane;
    class IModelViewPlaneFilter;
    class IGraphicsElementShape;
    class IGraphicsStyle;
    class IGraphicsStyleData;
    class IGraphicsStyleDataOverrideItems;
    class IGraphicsMaterial;
    class IGraphicsMaterialData;
    class IElementVisibilityFilter;
    class IElementInvalidFilter;
    class UniIdentity;
    class IModelViewEvent;
    struct DiscreteEpsilon;
    enum class GraphicsNodeVisibility;
    class IStaticContoursSegmentInfo;
    // 以下需改为接口
    class VisibilityGraphics;

    typedef std::map<ElementId, WeakPtr<const IGraphicsElementShape>> GraphicsElementShapes;

    /// \brief 图纸类型
    ///
    /// GCMP内置的图纸类型
    SERIALIZABLE_ENUM_CLASS(BuiltInViewType)
    {
        InValid = 0,            ///< 无效视图
        TwoDimensional,         ///< 2D视图
        ThreeDimensional,       ///< 3D视图
        Perspective,            ///< 透视视图
        Drawing                 ///< 图纸视图
    };

    /// \brief 可见 ELement 的前背景信息
    ENUM_CLASS(ElementForegroundOrBackgroundInfo)
    {
        Background = 0,         ///< 背景，平台渲染时忽略 GraphicsNode 上的前背景设置
        Foreground = 1,         ///< 前景，平台渲染时忽略 GraphicsNode 上的前背景设置
        Both = 2,               ///< 前背景，平台已经在 GraphicsNode 上设置了前背景信息，并以此来渲染
        Customize = 3,          ///< 用户自定义，由用户在 GraphicsNode 上设置前背景，如果没有设置，平台则使用背景渲染
    };

    /// \brief ElementShape 切面的类型
    ENUM_CLASS(ViewRangeCutter)
    {
        TopPlane = 1,               ///< 顶平面切割
        CutPlane = 2,               ///< 切平面切割
        PlanRegionCutPlane = 3      ///< 平面区域切面切割
    };

    ENUM_CLASS(CutGrepType)
    {
        Body = 0x1,                    ///< 切到了体
        Curve = 0x1 << 1               ///< 切到了线
    };

    /// \brief 视图接口
    ///
    /// 文档数据的图形表达
    class GCMP_MODEL_INTERFACE_EXPORT IModelView : public IElement
    {
        DEFINE_CAST_DERIVED(gcmp::IModelView, gcmp::IElement);

    public:
        virtual ~IModelView();

#pragma region static methods
        /// \brief 获取Implementation Uid
        ///
        /// \return UniIdentity 返回ImplementationUid
        static UniIdentity GetImplementationUid();

        /// \brief 获取文档中所有的视图
        /// \param pDoc 文档指针
        /// \return 所有视图
        static std::vector<IModelView*> GetAllModelViews(const IDocument* pDoc);

        /// \brief 获取文档中所有的视图的ElementId
        /// \param pDoc 文档指针
        /// \return 所有视图的ElementId
        static std::vector<ElementId> GetAllModelViewIds(const IDocument* pDoc);

        /// \brief 创建视图
        /// \param pDoc 文档指针
        /// \param viewName 视图名称
        /// \param viewDirection 视图方向
        /// \param origin 视图原点
        /// \param rightDirection 视图右方向
        /// \param upDirection 视图上方向
        /// \param viewType 视图类型
        /// \param creationOption 元素创建选项,可设置为永久(Normal)或临时对象
        /// \return 新创建的视图
        static IModelView* Create(IDocument* pDoc,const std::wstring& viewName, const BuiltInViewType& viewType,
            const Vector3d& viewDirection,
            const Vector3d& origin,
            const Vector3d& rightDirection,
            const Vector3d& upDirection,
            ElementCreationOptions creationOption = ElementCreationOptions::Normal);

        /// \brief 将视图显示模式和视图设置合并转成整型
        /// \param displayMode 视图显示模式
        /// \param displayOptions 视图设置
        /// \return 转换后的整型
        static int32_t ConvertDisplayModeAndOptionsToInt(ModelViewDisplayMode displayMode,
            const ModelViewDisplayOptions &displayOptions);

        /// \brief 将整型转成对应的视图显示模式和视图设置
        /// \param value 转换前的整型
        /// \param displayMode 视图显示模式
        /// \param displayOptions 视图设置
        static void ConvertIntToDisplayModeAndOptions(int32_t value, ModelViewDisplayMode &displayMode,
            ModelViewDisplayOptions &displayOptions);

#pragma endregion static methods

        /// \brief 获取视图名称
        /// \return 视图名称
        virtual const std::wstring& GetName() const = 0;
        /// \brief 设置视图名称
        /// \param newName 新名称
        /// \return 是否设置成功
        virtual bool SetName(const std::wstring& newName) = 0;

        /// \brief 获取视图原点
        /// \return 视图原点
        virtual Vector3d GetOrigin() const = 0;
        /// \brief 设置视图原点
        /// \param origin 新的原点
        /// \return 是否设置成功
        virtual bool SetOrigin(const Vector3d& origin) = 0;
        /// \brief 设置视图原点高度
        /// \param height 新高度
        virtual void SetOriginHeight(double height) = 0;
        /// \brief 标记视图原点已发生改变
        virtual void MarkOriginRdId() = 0;
        /// \brief （临时，可能移除）获取视图原点关联更新RdId
        /// \return 视图原点关联更新RdId
        virtual RegenDataId GetOriginRdId() const = 0;

        /// \brief 获取视图方向
        /// \return 视图方向
        virtual Vector3d GetViewDirection() const = 0;
        /// \brief 设置视图方向
        /// \param viewDirection 新的方向
        /// \return 是否设置成功
        virtual bool SetViewDirection(const Vector3d& viewDirection) = 0;
        /// \brief 标记视图方向已发生改变
        virtual void MarkViewDirectionRdId() = 0;        
        /// \brief （临时，可能移除）获取视图方向关联更新RdId
        /// \return 视图方向关联更新RdId
        virtual RegenDataId GetViewDirectionRdId() const = 0;

        /// \brief 获取视图右方向
        /// \return 视图右方向
        virtual Vector3d GetRightDirection() const = 0;
        /// \brief 设置视图右方向
        /// \param rightDirection 新的右方向
        /// \return 是否设置成功
        virtual bool SetRightDirection(const Vector3d& rightDirection) = 0;
        /// \brief 标记视图右方向已发生改变
        virtual void MarkRightDirectionRdId() = 0;
        /// \brief （临时，可能移除）获取视图右方向关联更新RdId
        /// \return 视图右方向关联更新RdId
        virtual RegenDataId GetRightDirectionRdId() const = 0;

        /// \brief 获取视图上方向
        /// \return 视图上方向
        virtual Vector3d GetUpDirection() const = 0;
        /// \brief 设置视图上方向
        /// \param upDirection 新的上方向
        /// \return 是否设置成功
        virtual bool SetUpDirection(const Vector3d& upDirection) = 0;
        /// \brief 标记视图上方向已发生改变
        virtual void MarkUpDirectionRdId() = 0;
        /// \brief （临时，可能移除）获取视图上方向关联更新RdId
        /// \return 视图上方向关联更新RdId
        virtual RegenDataId GetUpDirectionRdId() const = 0;

        /// \brief 获取视图缩放比例
        /// \return 视图视图缩放比例
        virtual double GetViewScale() const = 0;
        /// \brief 设置视图缩放比例
        /// \param viewScale 新的缩放比例
        /// \return 是否设置成功
        virtual void SetViewScale(double viewScale) = 0;
        /// \brief 获取视图缩放比例关联更新RdId
        /// \return 视图缩放比例关联更新RdId
        virtual RegenDataId GetViewScaleRdId() const = 0;

        /// \brief 判定是否引用的是剖切视图的ModelView
        /// \return 是否是剖切视图
        virtual bool IsSectionView() const = 0;

        /// \brief 获取内置视图类型
        /// \return 内置视图类型
        virtual const BuiltInViewType GetViewType() const = 0;

        /// \brief 设置内置视图类型
        /// \param viewType 新的类型
        /// \return 是否设置成功
        virtual bool SetViewType(const BuiltInViewType viewType) = 0;

        /// \brief 获取视图中 IWorkPlane 实例的ElementId
        /// \brief IWorkPlane 实例中缓存有默认的工作平面
        /// \return 工作平面Id
        virtual ElementId GetWorkPlaneId() const = 0;

        /// \brief 设置工作平面的平面（ 会根据传入平面的参数生成一个平面缓存到 IWorkPlane）
        /// \param plane 平面
        /// \return 是否设置成功
        virtual bool SetWorkPlane(const IPlane* plane) = 0;

        /// \brief 获取视图当前使用的工作平面（由于存在视图旋转、重新设置其他参考面等情况，该接口所获取到的平面可能和 SetWorkPlane 设置的平面不一致）
        /// \brief 首先获取全局工作平面（如有），其次尝试获取工作平面的参考面（如有）的平面
        /// \brief 若无上述两种类型平面，二维视图会根据视图右 、上方向新生成一个面做为工作平面，其他视图类型则会将 IWorkPlane 中缓存的默认平面克隆一份返回
        /// \brief 该接口获取的是视图当前使用的工作平面，仅需要获取默认工作平面请使用 GetWorkPlaneId() 获取
        /// \return 当前视图使用的工作平面
        virtual OwnerPtr<IPlane> GetWorkPlane() const = 0;

        /// \brief 获取视图关联标记
        /// \return 视图关联标记
        virtual ElementId GetViewSymbolId() const = 0;
        /// \brief 设置视图关联标记
        /// \param viewSymbolId 新的关联标记
        /// \return 是否设置成功
        virtual bool SetViewSymbolId(ElementId viewSymbolId) = 0;

        /// \brief 获取视图显示模式
        /// \return 视图显示模式
        virtual ModelViewDisplayMode GetDisplayMode() const = 0;
        /// \brief 设置视图显示模式
        /// \param displayMode 新的显示模式
        /// \return 是否设置成功
        virtual void SetDisplayMode(ModelViewDisplayMode displayMode) = 0;
        /// \brief 获取视图显示配置
        /// \return 视图显示配置，非实体模式下，光照、材质、显示边的配置项的值无效，不代表实际效果
        virtual ModelViewDisplayOptions GetDisplayOptions() const = 0;
        /// \brief 设置视图显示配置
        /// \param displayOptions 视图显示配置
        /// \return 是否设置成功，光照、材质、显示边只在实体模式下可以配置，其他模式设置失败；所有配置设置成功才算设置成功
        virtual bool SetDisplayOptions(const ModelViewDisplayOptions &displayOptions) = 0;

        /// \brief 获取静态轮廓线配置信息
        /// \return 静态轮廓线配置信息
        virtual const IStaticContoursSegmentInfo* GetStaticContoursSegmentInfo() const = 0;
        /// \brief 获取静态轮廓线配置信息
        /// \return 静态轮廓线配置信息，允许用户根据返回值修改配置信息
        virtual IStaticContoursSegmentInfo* GetStaticContoursSegmentInfoFw() = 0;
        /// \brief 设置静态轮廓线配置信息
        /// \param staticContoursSegmentInfo 静态轮廓线配置信息
        /// \return 是否设置成功
        virtual bool SetStaticContoursSegmentInfo(OwnerPtr<IStaticContoursSegmentInfo> staticContoursSegmentInfo) = 0;

        /// \brief 获取视图显示详细程度
        /// 
        /// \return 详细程度
        virtual ModelViewDetailLevel GetDetailLevel() const = 0;
        /// \brief 设置视图显示详细程度
        ///       
        /// \param level 详细程度
        virtual void SetDetailLevel(ModelViewDetailLevel level) = 0;

        /// \brief 获取视图显示替换模式
        /// 
        /// \return 视图显示替换模式
        virtual ModelViewReplaceMode GetReplaceMode() const = 0;
        
        /// \brief 设置视图显示替换模式
        ///       
        /// \param replaceMode 替换模式
        /// \return 是否设置成功
        virtual bool SetReplaceMode(ModelViewReplaceMode replaceMode) = 0;

        /// \brief 获取罗盘是否可见
        /// \return 是否可见
        virtual bool IsElementLocatorVisible() const = 0;
        /// \brief 显示罗盘
        /// \return 是否设置成功
        virtual bool ShowElementLocator() = 0;
        /// \brief 隐藏罗盘
        /// \return 是否设置成功
        virtual bool HideElementLocator() = 0;

        /// \brief 获取视图裁剪范围的ElementId
        /// \return 视图裁剪范围的ElementId
        virtual ElementId GetViewClipRangeId() const = 0;
        
        /// \brief 获取视图是否被视口裁剪面裁剪
        /// \return 是否裁剪
        virtual bool IsCroppedByViewport() const = 0;
        
        /// \brief 设置视图是否被视口裁剪面裁剪
        /// \param crop 是否裁剪
        /// \return 是否设置成功
        virtual bool CropByViewport(bool crop) = 0;

        /// \brief 获取视图注释裁剪（注意：视口裁剪框开启注释裁剪框才有效）
        /// \return 是否裁剪
        virtual  bool IsEnableAnnotationClip() const  = 0;
        /// \brief 设置视图注释裁剪（注意：视口裁剪框开启注释裁剪框才有效）
        /// \param enableAnnotationClip 是否裁剪
        /// \return 是否设置成功
        virtual bool SetEnableAnnotationClip(bool  enableAnnotationClip) = 0;

        /// \brief 创建矩形视口裁剪面
        /// \param leftOffset 基于视图原点的左偏移
        /// \param rightOffset 基于视图原点的右偏移
        /// \param upOffset 基于视图原点的上偏移
        /// \param downOffset 基于视图原点的下偏移
        /// \return 是否创建成功
        virtual bool CreateDefaultRectViewport(double leftOffset, double rightOffset, double upOffset, double downOffset) = 0;

        /// \brief （临时，可能移除）获取视图范围(包括视口、顶面、剖切面、底面、深度面、剖面盒)关联更新RdId
        /// \return 视图范围关联更新RdId
        virtual RegenDataId GetRangeUpdatedRdId() const = 0;

        /// \brief 标记视图范围已发生改变
        virtual void MarkRangeUpdatedRdId() = 0;

        /// \brief 获取视口裁剪面的平面
        /// \return 所有裁剪面的平面
        virtual std::vector<OwnerPtr<IGraphicsPlane>> GetAllViewportClipPlanes() const = 0;
        
        /// \brief 添加视图深度方向裁剪面
        /// \param offset 基于视图原点，视图方向的偏移
        /// \return 是否添加成功
        virtual bool AddCutPlane(double offset) = 0;
        /// \brief 更新视图深度方向裁剪面
        /// \param newOffset 基于视图原点，视图方向的偏移
        /// \return 是否更新加成功
        virtual bool UpdateCutPlane(double newOffset) = 0;
        /// \brief 获取视图深度方向裁剪面的偏移
        /// \param offset 基于视图原点，视图方向的偏移
        /// \return 是否获取成功
        virtual bool GetCutPlaneOffset(double& offset) const = 0;
        /// \brief 删除视图深度方向裁剪面
        /// \return 是否删除成功
        virtual bool DeleteCutPlane() = 0;

        /// \brief 添加视图深度方向顶面
        /// \param offset 基于视图原点，视图方向的偏移
        /// \return 是否添加成功
        virtual bool AddTopPlane(double offset, bool enableCut = false) = 0;
        /// \brief 更新视图深度方向顶面
        /// \param newOffset 基于视图原点，视图方向的偏移
        /// \return 是否更新加成功
        virtual bool UpdateTopPlane(double newOffset) = 0;
        /// \brief 获取视图深度方向顶面的偏移
        /// \param offset 基于视图原点，视图方向的偏移
        /// \return 是否获取成功
        virtual bool GetTopPlaneOffset(double& offset) const = 0;
        /// \brief 删除视图深度方向顶面
        /// \return 是否删除成功
        virtual bool DeleteTopPlane() = 0;

        /// \brief 添加视图深度方向底面
        /// \param offset 基于视图原点，视图方向的偏移
        /// \enableCut 是否开启裁剪，默认不开启裁剪。如果开启裁剪，使用渲染裁剪
        /// \return 是否添加成功
        virtual bool AddBottomPlane(double offset, bool enableCut = false) = 0;
        /// \brief 添加视图深度方向底面
        /// \param offset 基于视图原点，视图方向的偏移
        /// \enableCut 是否开启裁剪
        /// \useRenderCrop，是否使用渲染裁剪
        /// \return 是否添加成功
        virtual bool AddBottomPlane(double offset, bool enableCut, bool useRenderCrop) = 0;
        /// \brief 更新视图深度方向底面
        /// \param newOffset 基于视图原点，视图方向的偏移
        /// \return 是否更新加成功
        virtual bool UpdateBottomPlane(double newOffset) = 0;
        /// \brief 获取视图深度方向底面的偏移
        /// \param offset 基于视图原点，视图方向的偏移
        /// \return 是否获取成功
        virtual bool GetBottomPlaneOffset(double& offset) const = 0;
        /// \brief 删除视图深度方向底面
        /// \return 是否删除成功
        virtual bool DeleteBottomPlane() = 0;
        /// \brief （临时，可能移除）获取视图深度方向底面偏移RdId
        /// \return 深度方向底面偏移RdId
        virtual RegenDataId GetBottomPlaneOffsetRdId() const = 0;

        /// \brief 添加视图深度方向深度面
        /// \param offset 基于视图原点，视图方向的偏移
        /// \return 是否添加成功
        virtual bool AddDeepPlane(double offset, bool enableCut = false) = 0;
        /// \brief 更新视图深度方向深度面
        /// \param newOffset 基于视图原点，视图方向的偏移
        /// \return 是否更新加成功
        virtual bool UpdateDeepPlane(double newOffset) const= 0;
        /// \brief 获取视图深度方向深度面的偏移
        /// \param offset 基于视图原点，视图方向的偏移
        /// \return 是否获取成功
        virtual bool GetDeepPlaneOffset(double& offset) const = 0;
        /// \brief 删除视图深度方向深度面
        /// \return 是否删除成功
        virtual bool DeleteDeepPlane() = 0;

        /// \brief 获取视图平面过滤器
        /// \return 过滤器
        virtual const IModelViewPlaneFilter* GetModelViewPlaneFilter() const = 0;
        /// \brief 设置视图平面过滤器
        /// \param opPlaneFilter 视图平面过滤器用于设置是否需要忽略视图深度方向的平面
        virtual void SetModelViewPlaneFilter(OwnerPtr<IModelViewPlaneFilter> opPlaneFilter) = 0;

        /// \brief 获取视图剖面盒（如有）
        /// \return 剖面盒Id
        virtual ElementId GetSectionBoxId() const = 0;
        /// \brief 设置视图剖面盒
        /// \param sectionBoxId 剖面盒Id
        virtual void SetSectionBoxId(const ElementId& sectionBoxId) = 0;

        /// \brief  获取SectionBoxId的关联更新id 
        /// \return 获取的SectionBoxId的RegenDataId
        virtual RegenDataId GetSectionBoxIdRdId() const = 0;

        /// \brief 标记SectionBoxId已发生改变
        virtual void MarkSectionBoxIdRdId() = 0;

        /// \brief 设置剖切框是否使用渲染裁剪
        /// \param isCroppedByRender ture，使用渲染裁剪；false，使用模型数据裁剪
        /// \return true，设置成功；false，设置失败。当剖切框和裁剪框同时存在时，剖切框打开渲染裁剪会失败
        virtual bool SetIsRenderCropEnabledForSectionBox(bool isRenderCropEnabled) = 0;
        /// \brief 剖切框是否使用渲染裁剪
        /// \return true, 使用渲染裁剪；false，使用模型数据裁剪
        virtual bool IsRenderCropEnabledForSectionBox() const = 0;

        /// \brief 剖切框是否开启补面, 默认开启. 目前只对渲染裁剪有效
        virtual void SetIsClipPlaneFillFaceForSectionBox(bool IsClipPlaneFillFace) = 0;
        /// \brief 剖切框是否开启补面, 默认开启. 目前只对渲染裁剪有效
        /// \return true, 补面；false，不补面
        virtual bool IsClipPlaneFillFaceForSectionBox() const = 0;

        /// \brief 设置该视图下轮廓线是否绘制的阈值
        /// 
        /// 构件包围盒在当前视图方向下投影后宽高与当前视图下屏幕能显示的三维场景中的宽高之比小于下面给定的值时，构件不会绘制轮廓线
        /// 当threshold小于等于0，构件无论多小都会绘制轮廓线，平台会设置默认值， 默认值为0.005；
        ///  设置后轮廓线不会立马重新计算
        ///
        /// \param threshold 设置的阈值
        /// \return 
        virtual void SetContourLineCalculationThreshold(double threshold) = 0;

        /// \brief 获取该视图下轮廓线是否绘制的阈值
        /// 
        /// 当没有设置轮廓线是否绘制的阈值，会返回平台给定的默认值0.005；
        /// \return 轮廓线是否绘制的阈值
        virtual double GetContourLineCalculationThreshold() const = 0;

        /// \brief 设置该视图分批加载功能中grep是否绘制的阈值
        /// 
        /// 构件包围盒在当前视图方向下投影后宽高与当前视图下屏幕能显示的三维场景中的宽高之比小于下面给定的值时，构件不会在第一时间加载
        /// 当threshold小于等于0，构件无论多小都会绘制，平台默认值是0；范围是0-1之间；
        ///
        /// \param threshold 设置的阈值
        /// \return 
        virtual void SetGraphicsElementShapeCalculationThresholdForBatchLoad(double threshold) = 0;

        /// \brief 获取当前视图分批加载功能中grep是否绘制的阈值
        /// 
        /// \return 分批加载功能grep是否绘制的阈值
        virtual double GetGraphicsElementShapeCalculationThresholdForBatchLoad() const = 0;

        /// \brief 获取视图级离散精度
        ///
        /// 其中角度精度值，单位是弧度，如一个圆离散成 8 份应该写成 Constants::MATH_2PI / 8.0
        /// \param epsilon 视图离散精度
        virtual void GetDiscreteEpsilon(DiscreteEpsilon& epsilon) const = 0;

        /// \brief 设置视图级离散精度
        ///
        /// 注意:
        /// 1、其中角度精度值，单位是弧度，如一个圆离散成 8 份应该写成 Constants::MATH_2PI / 8.0
        /// 2、视图级离散精度，会覆盖全局离散精度（IMeshDiscretizeOptions) 以及 IGraphicsBRepBody里的离散精度
        /// 3、距离、角度精度小于0时，无效
        /// \param epsilon 离散精度值 
        /// \return 设置成功返回true，否则返回false
        virtual bool SetDiscreteEpsilon(const DiscreteEpsilon& epsilon) = 0;

        /// \brief 通过类别uid设置Element在视图中的可见性
        /// \param categoryUid 目标类别uid
        /// \param isVisible 是否可见
        virtual void SetElementsVisibilityByCategoryUid(const UniIdentity& categoryUid, bool isVisible) = 0;

        /// \brief 通过类别uid获取Element在视图中的可见性
        /// 
        /// 只考虑类别对Element在当前视图可见性的影响
        /// \param categoryUid 目标类别uid
        /// \return true-可见，false-不可见
        virtual bool GetElementsVisibilityByCategoryUid(const UniIdentity& categoryUid) const = 0;

        /// \brief 通过Element的id设置单个Element在视图中的可见性
        /// \param elementId 目标Element的id
        /// \param isVisible 是否可见
        virtual void SetElementVisibilityByElementId(const ElementId& elementId, bool isVisible) = 0;

        /// \brief 通过Element的id获取单个Element在视图中的可见性
        /// 
        /// 只通过ElementId识别Element在当前视图中的可见性
        /// \param elementId 目标Element的id
        /// \return true-可见，false-不可见
        virtual bool GetElementVisibilityByElementId(const ElementId& elementId) const = 0;

        /// \brief 添加Element可见性过滤器
        /// \param opFilter Element可见性过滤器
        /// \return true-添加成功，false-添加失败（包括：opFilter为空、过滤器名字为空、同名过滤器已存在）
        virtual bool AddElementVisibilityFilter(OwnerPtr<IElementVisibilityFilter> opFilter) = 0;

        /// \brief 添加Element可见性过滤器
        ///
        /// 在可见性过滤器中有自定义数据，并希望ModelView对象和自定义数据一起存储的时候，使用该接口。
        ///
        /// \param opFilter Element可见性过滤器
        /// \param moduleGroupGuid 自定义数据所属模块组
        /// \return true-添加成功，false-添加失败（包括：opFilter为空、过滤器名字为空、同名过滤器已存在、已有属于其它模块组的过滤器存在）
        virtual bool AddElementVisibilityFilter(OwnerPtr<IElementVisibilityFilter> opFilter, const Guid & moduleGroupGuid) = 0;

        /// \brief 删除Element可见性过滤器
        /// \param filterName Element可见性过滤器的名字
        /// \return true-删除成功，false-删除失败（过滤器不存在）
        virtual bool DeleteElementVisibilityFilter(const std::wstring& filterName) = 0;

        /// \brief 获取Element可见性过滤器
        /// \param filterName Element可见性过滤器的名字
        /// \return 名字为filterName的Element可见性过滤器，如果不存在，返回 nullptr
        virtual const IElementVisibilityFilter* GetElementVisibilityFilter(const std::wstring& filterName) const = 0;

        /// \brief 获取Element可见性过滤器
        /// \param filterName Element可见性过滤器的名字
        /// \return 名字为filterName的Element可见性过滤器，如果不存在，返回 nullptr
        virtual IElementVisibilityFilter* GetElementVisibilityFilterFw(const std::wstring& filterName) = 0;

        /// \brief 重载图形样式
        ///
        /// 针对类别的样式重载，可以只重载图形样式的部分字段
        /// \param categoryUid 需要重载图形样式的类别的 UniIdentity
        /// \param gstyleDataOverrideItems 指定图形样式中哪些字段需要重载
        /// \param gstyleData 指定图形样式中需要重载的那些字段的值
        /// \return 返回空
        virtual void OverrideGraphicsStyleByCategoryUid(const UniIdentity& categoryUid, const IGraphicsStyleDataOverrideItems& gstyleDataOverrideItems, const IGraphicsStyleData& gstyleData) = 0;

        /// \brief 获取图形样式重载信息
        /// \param categoryUid 重载图形样式的类别的 UniIdentity
        /// \return pair.first-指出图形样式中哪些字段被重载了，pair.second-对于图形样式数据中的字段，视图中如果没有重载，就是文档级类别对应样式的值，重载了，就是视图中对样式重载的值
        virtual std::pair<OwnerPtr<IGraphicsStyleDataOverrideItems>, OwnerPtr<IGraphicsStyleData>> GetGraphicsStyleOverrideByCategoryUid(const UniIdentity& categoryUid) const = 0;

        /// \brief 视图级重载给定构件上标记为tag的 graphic node 的样式
        ///
        /// 废弃!!!最好不要再新使用了!!!
        /// \param graphicsShapeElementId 构件ID，
        /// \param tag为构件下graphic node的tag标记，目前只对arc和line能设置 
        /// \param styleId为要设置的样式.  如需取消重载，把styleId设置为无效即可
        GCMP_DEPRECATED_API(2022 / 12 / 30) virtual void OverrideGraphicsStyleByGraphicsNodeTag(const ElementId& graphicsShapeElementId, const Guid &tag, const ElementId &styleId) const = 0;

        /// \brief 获取当前视图级 构件下标记为tag的关联的样式
        ///
        /// 废弃!!!最好不要再新使用了!!!
        /// \param graphicsShapepElementId 构件ID
        /// \param  tag  为构件下graphic node的tag标记
        /// \return 返回当前构建下tag所指定的样式,如果没指定，则为无效的ID
        GCMP_DEPRECATED_API(2022 / 12 / 30) virtual ElementId GetOverriddenGraphicsStylesByGraphicsNodeTag(const ElementId& graphicsShapeElementId, const Guid &tag) const = 0;

        /// \brief 视图级重载给定构件上样式名为styleName 的 graphic node 的样式
        ///
        /// \param graphicsShapeElementId 构件ID，
        /// \param styleName为构件下graphic node的样式名
        /// \param styleId为要设置的样式.  如需取消重载，把styleId设置为无效即可
        virtual void OverrideElementGraphicsStyleByStyleName(const ElementId& graphicsShapeElementId, const std::wstring &styleName, const ElementId &styleId) const = 0;

        /// \brief 获取当前视图级构件下样式名styleName关联的样式
        ///
        /// \param graphicsShapepElementId 构件ID
        /// \return std::map<std::wstring, ElementId>  返回通过构件上graphic node的样式名styleName重载的样式map
        virtual const std::map<std::wstring, ElementId>& GetOverriddenElementGraphicsStylesByStyleName(const ElementId& graphicsShapeElementId) const = 0;

        /// \brief 视图级重载给定构件上样式类别为categoryUid 的 graphic node 的样式
        ///
        /// \param graphicsShapeElementId 构件ID，
        /// \param categoryUid为构件下graphic node的样式类别
        /// \param styleId为要设置的样式.  如需取消重载，把styleId设置为无效即可
        virtual void OverrideElementGraphicsStyleByCategoryUid(const ElementId& graphicsShapeElementId, const UniIdentity &categoryUid, const ElementId &styleId) const = 0;

        /// \brief 获取当前视图级 构件下样式类别categoryUid关联的样式
        ///
        /// \param graphicsShapepElementId 构件ID
        /// \return std::map<gcmp::UniIdentity, ElementId> 返回通过构件上graphic node的样式类别categoryUid重载的样式map
        virtual const std::map<gcmp::UniIdentity, ElementId>& GetOverriddenElementGraphicsStylesByCategoryUid(const ElementId& graphicsShapeElementId) const = 0;

        /// \brief 视图级重载给定构件上材质 名为materialName 的 graphic node 的材质
        ///
        /// \param graphicsShapeElementId 构件ID，
        /// \param materialName为构件下graphic node的材质名
        /// \param materialId为要设置的材质.  如需取消重载，把materialId设置为无效即可
        virtual void OverrideElementGraphicsMaterialByMaterialName(const ElementId& graphicsShapeElementId, const std::wstring &materialName, const ElementId &materialId) const = 0;

        /// \brief 获取当前视图级构件下材质名materialName关联的材质
        ///
        /// \param graphicsShapepElementId 构件ID
        /// \return std::map<std::wstring, ElementId>  返回通过构件上graphic node的材质名materialName重载的材质map
        virtual const std::map<std::wstring, ElementId>& GetOverriddenElementGraphicsMaterialByMaterialName(const ElementId& graphicsShapeElementId) const = 0;

        /// \brief 视图级重载给定构件上材质类别为categoryUid 的 graphic node 的材质
        ///
        /// \param graphicsShapeElementId 构件ID，
        /// \param categoryUid为构件下graphic node的材质targetCatergoryUid
        /// \param materialId为要设置的材质.  如需取消重载，把materialId设置为无效即可
        virtual void OverrideElementGraphicsMaterialByTargetCategoryUid(const ElementId& graphicsShapeElementId, const UniIdentity &targetCategoryUid, const ElementId &materialId) const = 0;

        /// \brief 获取当前视图级 构件下材质类别targetCategoryUid关联的材质
        ///
        /// \param graphicsShapepElementId 构件ID
        /// \return std::map<gcmp::UniIdentity, ElementId> 返回通过构件上graphic node的材质类别targetCategoryUid重载的材质map
        virtual const std::map<gcmp::UniIdentity, ElementId>& GetOverriddenElementGraphicsMaterialByTargetCategoryUid(const ElementId& graphicsShapeElementId) const = 0;

        /// \brief 视图级重载给定构件上样式名为styleName 的 graphic node 的可见性
        ///
        /// \param graphicsShapeElementId 构件ID，
        /// \param styleName为构件下graphic node的样式名
        /// \param visiblity为要重载的可见性
        virtual void OverrideElementVisibilityByStyleName(const ElementId& graphicsShapeElementId, const std::wstring &styleName, const gcmp::GraphicsNodeVisibility& visiblity) = 0;

        /// \brief 获取当前视图级构件下节点样式名styleName关联的可见性
        ///
        /// \param graphicsShapepElementId 构件ID
        /// \return std::map<std::wstring, GraphicsNodeVisibility> 通过构件上graphic node的样式名重载的可见性map
        virtual const std::map<std::wstring, GraphicsNodeVisibility>& GetElementVisibilityOverriddenByStyleName(const ElementId& graphicsShapeElementId) const = 0;

        /// \brief 取消当前视图级 构件下样式名styleName关联的可见性的重载
        ///
        /// \param graphicsShapepElementId 构件ID
        /// \param  styleName为构件下graphic node的样式名
        /// \return 无
        virtual void RemoveElementVisibilityOverrideByStyleName(const ElementId& graphicsShapeElementId, const std::wstring &styleName) const = 0;

        /// \brief 视图级重载给定构件上样式类别为categoryUid 的 graphic node 的可见性
        ///
        /// \param graphicsShapeElementId 构件ID，
        /// \param categoryUid为构件下graphic node的样式类别
        /// \param visibility为要重载的可见性
        virtual void OverrideElementVisibilityByCategoryUid(const ElementId& graphicsShapeElementId, const UniIdentity &categoryUid,const GraphicsNodeVisibility& visibility) const = 0;

        /// \brief 获取当前视图级 构件下样式类别categoryUid关联可见性
        ///
        /// \param graphicsShapepElementId 构件ID
        /// \return std::map<gcmp::UniIdentity, GraphicsNodeVisibility> 通过构件上graphic node的样式类别categoryUid重载的可见性map
        virtual const std::map<gcmp::UniIdentity, GraphicsNodeVisibility>& GetElementVisibilityOverriddenByCategoryUid(const ElementId& graphicsShapeElementId) const = 0;

        /// \brief 取消当前视图级 构件下类别为categoryUid关联的可见性重载
        ///
        /// \param graphicsShapepElementId 构件ID
        /// \param  styleName为构件下graphic node的样式名
        /// \return 无
        virtual void RemoveElementVisibilityOverrideByCategoryUid(const ElementId& graphicsShapeElementId, const UniIdentity &categoryUid) const = 0;

        /// \brief 重载类别的剖切面前景Elements的图形样式
        ///
        /// 针对类别的剖切面前景Elements的样式重载，可以只重载图形样式的部分字段
        /// \param categoryUid 需要重载剖切面前景Elements的图形样式的类别的 UniIdentity
        /// \param gstyleDataOverrideItems 指定图形样式中哪些字段需要重载
        /// \param gstyleData 指定图形样式中需要重载的那些字段的值
        /// \return 返回空
        virtual void OverrideForegroundGraphicsStyleByCategoryUid(const UniIdentity& categoryUid, const IGraphicsStyleDataOverrideItems& gstyleDataOverrideItems, const IGraphicsStyleData& gstyleData) = 0;

        /// \brief 获取类别的剖切面前景Elements的图形样式重载信息
        /// \param categoryUid 重载图形样式的类别的 UniIdentity
        /// \return pair.first-指出图形样式中哪些字段被重载了，pair.second-对于图形样式数据中的字段，视图中如果没有重载，就是文档级类别前景样式对应的值，重载了，就是视图中对前景样式重载的值
        virtual std::pair<OwnerPtr<IGraphicsStyleDataOverrideItems>, OwnerPtr<IGraphicsStyleData>> GetForegroundGraphicsStyleOverrideByCategoryUid(const UniIdentity& categoryUid) const = 0;

        /// \brief 重载图形样式
        /// 
        /// 针对单个 element 进行样式重载
        /// \param elementId 需要重载图形样式的 element 的 id
        /// \param graphicsStyleId 用来重载的目标图形样式的 id，如果传入无效 id，就取消对 elementId 指定的 element 样式的重载
        /// \return 返回空
        virtual void OverrideGraphicsStyleByElementId(const ElementId& elementId, const ElementId& graphicsStyleId) = 0;

        /// \brief 获取重载的图形样式
        /// \param elementId 重载图形样式的 element 的 id
        /// \return 重载的目标图形样式的 id
        virtual ElementId GetOverriddenGraphicsStyleByElementId(const ElementId& elementId) const = 0;

        /// \brief 移除所有通过函数 OverrideGraphicsStyleByElementId 重载的图形样式
        /// \return 返回空
        virtual void RemoveOverriddenGraphicsStyleOfAllElements() = 0;

        /// \brief 获取对象重载的样式
        /// \return std::unordered_map<ElementId, ElementId, ElementIdHash> 对象重载样式
        virtual const std::unordered_map<ElementId, ElementId, ElementIdHash>& GetElementGStyles() const = 0;

        /// \brief 重载图形材质
        /// \param categoryUid 需要重载图形材质的类别的 UniIdentity
        /// \param pGraphicsMaterialData 指定需要重载的图形材质数据，如果是 nullptr，就取消重载
        /// \return 返回空
        virtual void OverrideGraphicsMaterialByCategoryUid(const UniIdentity& categoryUid, const IGraphicsMaterialData* pGraphicsMaterialData) = 0;

        /// \brief 获取图形材质的重载数据
        /// \param categoryUid 重载图形材质的类别的 UniIdentity
        /// \return 图形材质的重载数据
        virtual OwnerPtr<IGraphicsMaterialData> GetGraphicsMaterialOverrideByCategoryUid(const UniIdentity& categoryUid) const = 0;

        /// \brief 重载图形材质
        /// \param elementId   Element的Id
        /// \param materialId  图形材质的ElementId;如果ElementId是无效的，相当于取消重载图形材质
        /// \return
        virtual void OverrideGraphicsMaterialByElementId(const ElementId &elementId, const ElementId &materialId) = 0;

        /// \brief 获取重载的图形材质
        /// \param elementId 重载图形材质的 element 的 id
        /// \return 重载的目标图形材质的 id
        virtual ElementId GetOverridedGraphicsMaterialByElementId(const ElementId& elementId) const = 0;

        /// \brief 重载视图的详细程度设置
        ///
        /// 针对类别的重载，可以控制某一类别在视图中显示哪一种程度的图形
        /// \param categoryUid 类别的 UniIdentity
        /// \param overrideDetailLevel 重载的详细程度枚举值
        /// \param 成功返回true，失败返回false
        virtual bool OverrideDetailLevelByCategoryUid(const UniIdentity& categoryUid, ModelViewDetailLevel overrideDetailLevel) = 0;

        /// \brief 清理指定对象在当前视图中的各种重载，包括，
        ///  1. element级的样式数据、材质数据 
        ///  2. 节点级的样式数据和材质数据、节点级的显隐数据
        /// 
        /// \param elementIds 需要清理的对象
        virtual void RemoveGraphicsStyleMaterialAndVisibilityOverriddenData(const std::set<ElementId>& elementIds) = 0;

        /// \brief 获取视图详细程度的重载设置
        ///
        /// \param categoryUid 重载的类别的 UniIdentity
        /// \return 返回重载的详细程度枚举值，如果返回ModelViewDetailLevel::Undefined，则代表未重载
        virtual ModelViewDetailLevel GetDetailLevelOverrideByCategoryUid(const UniIdentity& categoryUid) const = 0;

        /// \brief 获取类别是否重载了视图的详细程度设置
        ///
        /// \param categoryUid 类别的 UniIdentity
        /// \return true 类别重载了视图的详细程度设置；false则未重载
        virtual bool HasOverrideDetailLevel(const UniIdentity& categoryUid) const = 0;
         
        /// \brief 设置当前ELement置顶或置底
        /// \param elementId  当前构件ID
        /// \param info  目前只能为UnderlayUplayInfo所列举的枚举
        virtual void AddUnderLayUpLayInfo(const ElementId& elementId, int info) = 0;

        /// \brief 设置当前ELement置顶或置底
        /// \param elementIds  当前构件IDs
        /// \param info  目前只能为UnderlayUplayInfo所列举的枚举
        virtual void AddUnderLayUpLayInfos(const std::vector<ElementId>& elementIds, int info) = 0;

        /// \brief 取消当前elemet的置顶或置底信息
        ///
        ///AddUnderLayUpLayInfo（ElementId,  Normal_LayInfo）和RemoveUnderLayUpLayInfo有一些不同，
        ///如果是调用AddUnderLayUpLayInfo， 把info设置为Normal_LayInfo, 则当前视图当前构件以它设置的为准， 即不置顶也不置底.
        ///如果是RemoveUnderLayUpLayInfo， 则表示视图级没设置置顶置底信息，以文档级设置的为准
        ///AddUnderLayUpLayInfo（ElementId,  Unkown_LayInfo）和RemoveUnderLayUpLayInfo行为完全一致
        /// \param elementId   Element的Id
        virtual void RemoveUnderLayUpLayInfo(const ElementId& elementId) = 0;

        /// \brief 取消当前elemet的置顶或置底信息
        ///
        ///AddUnderLayUpLayInfo（ElementId,  Normal_LayInfo）和RemoveUnderLayUpLayInfo有一些不同，
        ///如果是调用AddUnderLayUpLayInfo， 把info设置为Normal_LayInfo, 则当前视图当前构件以它设置的为准， 即不置顶也不置底.
        ///如果是RemoveUnderLayUpLayInfo， 则表示视图级没设置置顶置底信息，以文档级设置的为准
        ///AddUnderLayUpLayInfo（ElementId,  Unkown_LayInfo）和RemoveUnderLayUpLayInfo行为完全一致
        /// \param elementIds   构件的Id数组
        virtual void RemoveUnderLayUpLayInfos(const std::vector<ElementId>& elementIds) = 0;

        /// \brief 取消所有element的置顶置底信息
        ///
        virtual void RemoveAllUnderLayUpLayInfos() = 0;

        /// \brief 返回所有视图级置底信息 (对GetUnderLayUpLayInfo返回的结果过滤，得到所有置底信息, 由于要构建一个新的set性能会略微差一些)       
        /// \return 所有置底信息
        virtual  std::set<ElementId> GetElementsInUnderLay() const = 0;

        /// \brief 返回所有视图级置顶信息(对GetUnderLayUpLayInfo返回的结果过滤，得到所有置顶信息, 由于要构建一个新的set性能会略微差一些)  
        /// \return 所有置顶信息
        virtual  std::set<ElementId> GetElementsInUpLay() const = 0;

        /// \brief 返回所有视图级置顶置底信息      
        /// \return 所有置顶置底信息
        virtual const std::map<ElementId, int>& GetUnderLayUpLayInfo() const = 0;

        
        /// \brief 获取所有平面区域对象elementId
        /// \return 所有平面区域对象elementId
        virtual const std::vector<gcmp::ElementId>& GetAllPlanRegions() const = 0;

        /// \brief   获取所有平面区域的RDID
        /// \return       RegenDataId
        virtual RegenDataId GetPlanRegionsRdId() const = 0;

        /// \brief 生成文档中所有Element在本视图中的图形表达
        /// \return 视图中缓存的图形表达
        virtual std::vector<const IGraphicsElementShape*> GenerateModelViewElementShapes() = 0;

        /// \brief 生成文档中所有Element在本视图中可见的图形表达
        /// 
        /// 得到视图中所有可见grep的拷贝（包括模型grep和视图grep),
        /// 若设置了视口裁剪真实裁剪(CropByViewport)，则得到的是裁剪后的grep
        /// 调用此接口不会产生视图grep的缓存;如果视图已打开，若更改了Element的图形表达，需确保视图已刷新，否则得到的可能不对
        /// \return 视图中见的图形表达的拷贝
        virtual std::vector<OwnerPtr<IGraphicsElementShape>> CreateVisibleElementShapesInModelView() = 0;

        /// \brief 得到文档中所有在本视图中可见的Element
        /// 
        /// 得到的结果与CreateVisibleElementShapesInModelView相同
        /// \return 文档中所有在本视图中可见的ElementId集
        virtual std::set<ElementId> GetVisibleElementIds() = 0;


        /// \brief 刷新视图 Grep (在增量更新过程中)
        /// \param inputElementIds 需要更新的Element
        /// \return void
        virtual void UpdateModelViewGraphicsElementShapes(const std::vector<ElementId>& inputElementIds) = 0;

        /// \brief 生成该Element在本视图中的图形表达
        /// \return 图形表达
        virtual OwnerPtr<IGraphicsElementShape> CreateModelViewElementShape(const IElement* pElement) const = 0;

        /// \brief 获取该Element在本视图中的图形表达
        /// \return 图形表达
        virtual const IGraphicsElementShape* GetModelViewElementShape(const ElementId& elementId) const = 0;

        /// \brief 清除本视图中缓存的图形表达
        virtual void ClearModelViewElementShapes() = 0;

        /// \brief 获得视图中范围中可见的图形表达
        /// 
        /// 开启裁剪框时获取裁剪框内可见的图形表达（之前的裁剪框和剖切框的行为相同，对框内的Grep进行真正的裁剪，
        /// 目前裁剪框使用视图裁剪的方式。为满足之前导出功能的使用方式，提供该方法）
        /// \return 可见的图形表达
        virtual const GraphicsElementShapes& GetVisibleModelViewElementShapes() const = 0;

        /// \brief 获得没有被裁剪框裁剪之前可见的图形表达(现在的裁剪框是视图裁剪，并没有对Grep进行真正的裁剪，该接口返回的是没有被裁剪框裁剪的可见视图)
        /// \return 可见的图形表达
        virtual const GraphicsElementShapes& GetVisibleModelViewElementShapesWithoutCroppedByViewPort() const = 0;

        /// \brief 从输入的图形表达中过滤出在没有被裁剪框裁剪之前可见的图形表达(现在的裁剪框是视图裁剪，并没有对Grep进行真正的裁剪，该接口返回的是没有被裁剪框裁剪的可见视图)

        /// \brief 从输入的图形表达中过滤出在本视图中可见的图形表达
        /// 
        /// 开启裁剪框时获取裁剪框内可见的图形表达（之前的裁剪框和剖切框的行为相同，对框内的Grep进行真正的裁剪，
        /// 目前裁剪框使用视图裁剪的方式。为满足之前导出功能的使用方式，提供该方法）
        /// \param inputGreps 输入的图形表达
        /// \return 可见的图形表达
        virtual std::vector<const IGraphicsElementShape*> GetVisibleModelViewElementShapes(const std::vector<const IGraphicsElementShape*>& inputGreps) const = 0;

        /// \brief 获得视图范围中所有可编辑的图形表达；可见可编辑的范围为视图顶面和底面之间的形体；可见不可编辑的范围为底面和深度面之间的形体。
        ///
        /// 图纸视图存在激活视口时，该接口所得Greps会在IUiView::GetEditableGreps()中被过滤
        /// \return 可编辑的图形表达
        virtual std::vector<const IGraphicsElementShape*> GetEditableModelViewElementShapes() const = 0;

        /// \brief 获得视图范围中所有不可编辑的图形表达；可见可编辑的范围为视图顶面和底面之间的形体；可见不可编辑的范围为底面和深度面之间的形体。
        /// \return 不可编辑的图形表达
        virtual std::vector<const IGraphicsElementShape*> GetUneditableModelViewElementShapes() const = 0;

        /// \brief 获取该视图下的前景对象
        /// 
        /// 前景对象指该Grep整个位于视图剖切平面之上的对象，不论该element是否可见；只对平面视图有效；
        /// \return 当前视图下的前景对象
        virtual std::set<ElementId> GetForegroundElements() const = 0;

        /// \brief 获取可见 Element 在本视图中的前背景信息
        /// \param elementId 要查询的 ELement 的 Id
        /// \param info ELement 的前背景信息
        /// \return true，获取信息成功；false，获取信息失败（Element 不可见）
        virtual bool GetVisibleElementForegroundOrBackgroundInfo(const ElementId& elementId, ElementForegroundOrBackgroundInfo& info) const = 0;

        /// \brief 判断Element在当前视图中是否可见
        /// 
        /// 考虑了以下因素对可见性的影响
        /// 1、Element类别对可见性的影响
        /// 2、文档级的可见性过滤
        /// 3、视图中的可见性过滤
        /// 4、视图中通过ElementId设置的可见性
        /// 5、IElementViewSpecificShapeComponent::IsVisibleInModelView
        /// 6、IElement::IsVisible
        /// 没有考虑以下因素：
        /// 2、视图范围剖切
        /// 3、GraphicsElementShape 是否存在
        /// 4、ModelViewGraphicsElementShape 上的可见性设置
        /// \param pElement 目标Element
        /// \param pInvisibleReason 如果不可见，返回其中一个不可见原因
        /// \return true-可见，false-不可见
        virtual bool IsElementVisible(const IElement* pElement, std::wstring* pInvisibleReason) const = 0;
        
        /// \brief 设置Element刪除组件接口
        /// \param opElementDeletionComponent 要设置的Element刪除组件
        /// \return 设置成功返回true，否则返回false
        /// \see IElementDeletionComponent
        virtual bool SetElementDeletionComponent(OwnerPtr<IElementDeletionComponent> opElementDeletionComponent) = 0;
        
        /// \brief 获取视图事件
        /// 支持的事件类型见ModelViewEventType
        /// \return 视图事件
        virtual IModelViewEvent* GetModelViewEvent() const = 0;

        ///shenz 在该ModelView对应的视图里开启动态精度（仅当视图细节程度为精细时生效，调整显示的精细程度，大幅降低内存占用，会导致缩放时比原来慢，内存16GB的机器可以考虑开启）
        ///三维和立面视图可以开启，平面视图不需要开启
        virtual void SetDynamicLod(bool bValue) = 0;
        virtual bool IsDynamicLod() const = 0;

        /// \brief 在下次视图刷新的时候离散 GraphicsElementShapes
        /// \param elementIds  需要离散的Element
        virtual void DiscretizeGraphicsElementShapes(const std::set<ElementId>& elementIds) = 0;

        /// \brief 在下次视图刷新的时候离散 GraphicsElementShapes
        ///
        /// 为 GraphicsElementShapes 生成对应的 renderable 用于渲染，从离散开始，不过大多数情况下不需要重新离散，除非带线型填充等
        /// \param elementIds 需要离散的Element
        /// \param supportUndoRedo 是否支持 undoRedo
        virtual void DiscretizeGraphicsElementShapes(const std::set<ElementId>& elementIds, bool supportUndoRedo) = 0;

        /// \brief 设置是否需要记录被构件是否被ViewRangeCutter剖切到的element
        /// 建议在创建视图后就设置此接口，若其它时机调用此接口，需调用GenerateModelViewElementShapes()生成缓存记录
        /// 只有记录后，才能调用GetVisibleElementCutInfoByViewRange
        /// \param needRecord  是否要记录(默认不记录)
        virtual void RecordElementsCutByViewRange(bool needRecord) = 0;

        /// \brief 从缓存中获取构件在当前视图的被切割信息
        /// 只有设置RecordElementsCutByViewRange(true)记录后，才能获取到正确信息
        /// \param elementId  需要查询的构件id
        /// \param cutInfos  为空表示grep整体没有被任何切面切到；key记录被什么面切割，value记录Grep被面切到部分标识位(CutGrepType)的集合（value为0表示没有与切面相交的部分）
        /// \return element不可见，或是没有记录则返回false，否则返回true
        virtual bool GetVisibleElementCutInfoByViewRange(ElementId elementId, std::map<ViewRangeCutter, Int32>& cutInfos) const = 0;

        //shenz 设置剖切视图范围框的偏移值（为了性能）
        //>=0为有效值，如果<0，则取gcmp内置的默认参数
//        virtual void SetClipOffsetParam(int nTopOffset, int nBottomOffset, int nLeftOffset, int nRightOffset) = 0;

        /// \brief 增量刷新前，根据外部缓存的element信息，过滤掉当前视图不需要的element，避免获取element后执行可见性判断等代码逻辑造成的开销 
        /// \param pFilter Filter指针，生命周期由产品管理
        virtual void SetElementInvalidFilter(const IElementInvalidFilter *pFilter) = 0;
        /// \brief 提供快速查询接口，供ElementsChangeHandlerWithFilter使用
        /// \param id element的id
        virtual bool IsElementInvalid(const ElementId &id) = 0;


        /// \brief 设置位置报告组件
        /// \param opElementPositionReportComponent 位置报告组件
        /// \return bool
        virtual bool SetElementPositionReportComponent(OwnerPtr<IElementPositionReportComponent> opElementPositionReportComponent) = 0;

        /// \brief 设置是否是协同链接的视图
        virtual void SetIsForGdcLink(bool isForGdcLink) = 0;
#pragma region DEPRECATED_API
        /// \brief 获取视图出图模式
        /// \return 视图出图模式
        GCMP_DEPRECATED_API(2020 / 08 / 01) virtual ModelViewDrawingMode GetDrawingMode() const = 0;

        /// \brief 设置视图出图模式
        /// \param drawingMode 新的出图模式
        /// \return 是否设置成功
        GCMP_DEPRECATED_API(2020 / 08 / 01) virtual void SetDrawingMode(ModelViewDrawingMode drawingMode) = 0;

        /// \brief 获取定制视图类型
        /// \return 定制视图类型
        /// \note 需要GBMP-5241完成后以及产品完成替换后才能删除
        GCMP_DEPRECATED_API(2020 / 09 / 01) virtual const std::wstring& GetUserDataId() const = 0;

        /// \brief 设置定制视图类型
        /// \param viewType 新的类型
        /// \return 是否设置成功
        /// \note 需要GBMP-5241完成后以及产品完成替换后才能删除
        GCMP_DEPRECATED_API(2020 / 09 / 01) virtual bool SetUserDataId(const std::wstring& viewType) = 0;

        /// \brief 获取视口裁剪面是否可见
        /// \return 是否可见
        GCMP_DEPRECATED_API(2022 / 06 / 30) virtual bool IsViewportVisible() const = 0;

        /// \brief 显示视口裁剪面
        /// \return 是否设置成功
        GCMP_DEPRECATED_API(2022 / 06 / 30) virtual bool ShowViewport() = 0;

        /// \brief 隐藏视口裁剪面
        /// \return 是否设置成功
        GCMP_DEPRECATED_API(2022 / 06 / 30) virtual bool HideViewport() = 0;

        /// \brief 获取矩形视口裁剪面的偏移
        /// \param leftOffset 基于视图原点的左偏移
        /// \param rightOffset 基于视图原点的右偏移
        /// \param upOffset 基于视图原点的上偏移
        /// \param downOffset 基于视图原点的下偏移
        /// \return 是否获取成功
        GCMP_DEPRECATED_API(2022 / 06 / 30) virtual bool GetDefaultRectViewport(double& leftOffset, double& rightOffset, double& upOffset, double& downOffset) const = 0;

        /// \brief 更新矩形视口裁剪面的偏移
        /// \param leftOffset 基于视图原点的左偏移
        /// \param rightOffset 基于视图原点的右偏移
        /// \param upOffset 基于视图原点的上偏移
        /// \param downOffset 基于视图原点的下偏移
        /// \return 是否更新成功
        GCMP_DEPRECATED_API(2022 / 06 / 30) virtual bool UpdateDefaultRectViewport(double leftOffset, double rightOffset, double upOffset, double downOffset) = 0;

        /// 
        /// \param inputGreps 输入的图形表达
        /// \return 可见的图形表达
        GCMP_DEPRECATED_API(2022 / 12 / 30) virtual std::vector<const IGraphicsElementShape*> GetVisibleModelViewElementShapesWithoutCroppedByViewPort(const std::vector<const IGraphicsElementShape*>& inputGreps) const = 0;
#pragma endregion DEPRECATED_API
    };
}


